
package rcpsp;

import data.Data;
import ilog.concert.IloException;
import ilog.cplex.IloCplex;
import java.io.File;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;


// main class for the RCPSP project
// authors : Rio Guillaume & Toullat Alexis
public class RCPSP {
    
    
    /**
     * Class for filtering files name extensions.
    */
    private class Filter implements FilenameFilter
    {
        @Override
        public boolean accept(File rep, String fichier) {

            if (fichier.endsWith(".sm") || fichier.endsWith(".class")){
                return true;
            }
            return false;
        }
    }
    
    String path;
    String[] nameFiles; 
    ArrayList<ArrayList<Integer>> objectives;
    ArrayList<ArrayList<Long>> times;
    long totalTimeToSolve;  //time in minutes...
    PrintWriter fil;
    
    private DecimalFormat ft = new DecimalFormat(); //To truncate numbers...
    
    public RCPSP(int nb){
        
        ft.setMaximumFractionDigits(nb);
        
        this.objectives = new ArrayList<>();
        this.times = new ArrayList<>();
        this.totalTimeToSolve = 0;
    }
    
    public void launchSimulation() throws IloException{
        
        totalTimeToSolve = System.nanoTime();
        
        path = System.getProperty("user.dir")+"//DATA//";
        
        File f = new File(path);
        f.mkdirs();
        
        // Lists all files which end by ".sm"
        nameFiles = new java.io.File(path + ".").list(new Filter());
        Arrays.sort(nameFiles);
        
        //Creates a list for each kind of model tested
        for (int i = 0; i < 3; i++) {
            objectives.add(new ArrayList<Integer>());
            times.add(new ArrayList<Long>());
        }
        
        //decides to test each model separately.
        // objectives[0] --> ModelForbidConflicts
        // objectives[1] --> ModelConflicts
        // objectives[2] --> ModelFlow
        // Same for times...
        
        initOutput(); //create File to write into
        
        for (int i=0; i<nameFiles.length; i++){
            try {
                Data dat = new Data(path + nameFiles[i]);
                dat.readFile();
                
                fil.println("Fichier : " + nameFiles[i]);
                
                
                IloCplex cplex = new IloCplex();
                cplex.setOut(null);
                ModelForbidConfig2 modelForbid = new ModelForbidConfig2(cplex, dat);
                modelForbid.createModel();
                modelForbid.solve();
                objectives.get(0).add(modelForbid.getResult().getObjSol());
                times.get(0).add(modelForbid.getResult().getTimeToSolve());
                fil.println(modelForbid.getResult().getObjSol() + "\t" + ft.format((double)modelForbid.getResult().getTimeToSolve() / (double)1000));
                fil.flush();
                
                
                cplex = new IloCplex();
                cplex.setOut(null);
                ModelConflicts modelConflit = new ModelConflicts(cplex, dat);
                modelConflit.createModel();
                modelConflit.solve();
                objectives.get(1).add(modelConflit.getResult().getObjSol());
                times.get(1).add(modelConflit.getResult().getTimeToSolve());
                fil.println(modelConflit.getResult().getObjSol() + "\t" + ft.format((double)modelConflit.getResult().getTimeToSolve() / (double)1000));
                fil.flush();
                
                
                cplex = new IloCplex();
                cplex.setOut(null);
                ModelFlow modelFlow = new ModelFlow(cplex, dat);
                modelFlow.createModel();
                modelFlow.solve();
                objectives.get(2).add(modelFlow.getResult().getObjSol());
                times.get(2).add(modelFlow.getResult().getTimeToSolve());
                fil.println(modelFlow.getResult().getObjSol() + "\t" + ft.format((double)modelFlow.getResult().getTimeToSolve() / (double)1000));
                fil.println("");
                fil.flush();
                
            } catch (IloException ex) {
                Logger.getLogger(RCPSP.class.getName()).log(Level.SEVERE, null, ex);
                throw new IloException("Problem");
            }
	}
        
        totalTimeToSolve = (System.nanoTime() - totalTimeToSolve) / 1000000;
        fil.println("====================================================");
        fil.println("");        
        fil.println("Temps total calcul \t : " + ft.format(((double)totalTimeToSolve / (double)(1000*60))) + " m");
        fil.close();
    }
    
    private void initOutput(){
        try {
            fil = null;
            String path2 = System.getProperty("user.dir")+"//Resultats//";
            File f = new File(path2);
            f.mkdirs();
            fil = new PrintWriter(new FileWriter(path2 + "Resultats.txt"));
            fil.println("Fichier contenant les résultats de chaque expérience");
            fil.println("====================================================");
            fil.println("Ordinateur\t \t : Z97");
            fil.println("Processeur\t \t : i7 4790k @ 4.4Ghz");
            fil.println("Mémoire vive\t \t : 16GB");
            fil.println("OS \t \t \t : VM Ubuntu 14.04 émulée sur Windows 7");
            fil.println("");
            fil.println("");
            fil.println("Syntaxe :");
            fil.println("");
            fil.println("fichier \t #NomDuFichier");
            fil.println("ModelForbidConflicts \t #ValFObj #tempsResol (s)");
            fil.println("ModelConflicts \t \t #ValFObj #tempsResol (s)");
            fil.println("ModelFlow \t \t #ValFObj #tempsResol (s)");
            fil.println("");
            fil.println("====================================================");
            fil.println("");
            fil.println("");
        } catch (IOException ex) {
            Logger.getLogger(RCPSP.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    
    public ArrayList<ArrayList<Integer>> getObjectives(){
        return objectives;
    }

    public String[] getNameFiles() {
        return nameFiles;
    }

    public ArrayList<ArrayList<Long>> getTimes() {
        return times;
    }
    

    public static void main(String[] args) throws IloException {
        
        RCPSP test = new RCPSP(2);
        test.launchSimulation();
    }
    
}
